﻿using NDF;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace System.Web.Mvc
{
    /// <summary>
    /// 表示一个特性，该特性用于标记在授权期间要跳过指定或所有的 <see cref="System.Web.Mvc.AuthorizeAttribute"/> 的控制器和操作。
    /// 该特性类似于 <see cref="System.Web.Mvc.AllowAnonymousAttribute"/>，但不同之处在于：
    ///     <see cref="System.Web.Mvc.AllowAnonymousAttribute"/> 指定 Controller 或 Action 跳过所有的 <see cref="System.Web.Mvc.AuthorizeAttribute"/> 验证；
    ///     <see cref="NDF.Web.Mvc.AllowAuthorizeAttribute"/> 指定 Controller 或 Action 可以跳过所有的 <see cref="System.Web.Mvc.AuthorizeAttribute"/> 验证，也可以只绕过特定的 <see cref="System.Web.Mvc.AuthorizeAttribute"/> 验证。
    /// 注意：要使该标记该特定的 Controller 或 Action 能够有效跳过验证，被添加至 <seealso cref="GlobalFilters.Filters"/> 的所有 AuthorizeAttribute 特性必须继承于类型 <see cref="NDF.Web.Mvc.NDFAuthorizeAttribute"/>。
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
    public sealed class AllowAuthorizeAttribute : Attribute
    {
        private Type _allowType;
        private bool _allowInherited = false;

        private static Type _authorizeAttributeType;


        /// <summary>
        /// 初始化一个 <see cref="NDF.Web.Mvc.Authorization.AllowAuthorizeAttribute"/> 对象。
        /// </summary>
        public AllowAuthorizeAttribute() { }

        /// <summary>
        /// 以指定的参数初始化一个 <see cref="NDF.Web.Mvc.Authorization.AllowAuthorizeAttribute"/> 对象。
        /// </summary>
        /// <param name="allowType">表示该 <see cref="NDF.Web.Mvc.Authorization.AllowAuthorizeAttribute"/> 特性指示可以跳过哪个 AuthorizeAttribute 类型提供的授权验证服务。</param>
        public AllowAuthorizeAttribute(Type allowType) : this()
        {
            Guard.ArgumentNotNull(allowType, "allowType");
            this.AllowType = allowType;
        }

        /// <summary>
        /// 以指定的参数初始化一个 <see cref="NDF.Web.Mvc.Authorization.AllowAuthorizeAttribute"/> 对象。
        /// </summary>
        /// <param name="allowInherited">
        /// 该值指示当用特性 <see cref="NDF.Web.Mvc.Authorization.AllowAuthorizeAttribute"/> 指示某个 Controller 或 Action 跳过特定的授权验证服务时，如果
        /// 特性 <see cref="NDF.Web.Mvc.Authorization.AllowAuthorizeAttribute"/> 指定了 <seealso cref="AllowType"/> 值时，除 <seealso cref="AllowType"/> 标识的授权验证类被跳过
        /// 外，是否连同 <seealso cref="AllowType"/> 标识的授权验证类继承链子类所有的验证服务一并跳过。
        /// </param>
        public AllowAuthorizeAttribute(bool allowInherited) : this()
        {
            this.AllowInherited = allowInherited;
        }

        /// <summary>
        /// 以指定的参数初始化一个 <see cref="NDF.Web.Mvc.Authorization.AllowAuthorizeAttribute"/> 对象。
        /// </summary>
        /// <param name="allowType">
        /// 该值指示当用特性 <see cref="NDF.Web.Mvc.Authorization.AllowAuthorizeAttribute"/> 指示某个 Controller 或 Action 跳过特定的授权验证服务时，如果
        /// 特性 <see cref="NDF.Web.Mvc.Authorization.AllowAuthorizeAttribute"/> 指定了 <seealso cref="AllowType"/> 值时，除 <seealso cref="AllowType"/> 标识的授权验证类被跳过
        /// 外，是否连同 <seealso cref="AllowType"/> 标识的授权验证类继承链子类所有的验证服务一并跳过。
        /// </param>
        /// <param name="allowInherited">表示该 <see cref="NDF.Web.Mvc.Authorization.AllowAuthorizeAttribute"/> 特性指示可以跳过哪个 AuthorizeAttribute 类型提供的授权验证服务。</param>
        public AllowAuthorizeAttribute(Type allowType, bool allowInherited)
            : this(allowType)
        {
            this.AllowInherited = allowInherited;
        }

        /// <summary>
        /// 获取或设置可以跳过的指定的 AuthorizeAttribute 类型。
        /// 该属性指示在授权期间可以跳过具体由哪个 AuthorizeAttribute 特性提供的授权验证服务；
        /// 如果指定该属性，则其所表示的 AuthorizeAttribute 特性类型必须继承于类型 <see cref="NDF.Web.Mvc.NDFAuthorizeAttribute"/>。
        /// </summary>
        public Type AllowType
        {
            get { return this._allowType; }
            set
            {
                if (NDFAuthorizeAttribute.IsAssignableFrom(value))
                {
                    this._allowType = value;
                }
                else
                {
                    throw new ArgumentException("属性 AllowType 设置的值应该是 NDF.Web.Mvc.Authorization.NDFAuthorizeAttribute 类型对象或者是它的子类对象。", "AllowType");
                }
            }
        }

        /// <summary>
        /// 获取或设置一个布尔值，该值指示当用特性 <see cref="NDF.Web.Mvc.Authorization.AllowAuthorizeAttribute"/> 指示某个 Controller 或 Action 跳过特定的授权验证服务时，如果
        /// 特性 <see cref="NDF.Web.Mvc.Authorization.AllowAuthorizeAttribute"/> 指定了 <seealso cref="AllowType"/> 值时，除 <seealso cref="AllowType"/> 标识的授权验证类被跳过
        /// 外，是否连同 <seealso cref="AllowType"/> 标识的授权验证类继承链子类所有的验证服务一并跳过。该值默认为 false。
        /// </summary>
        public bool AllowInherited
        {
            get { return this._allowInherited; }
            set { this._allowInherited = value; }
        }

        /// <summary>
        /// 获取能够用 <see cref="NDF.Web.Mvc.Authorization.AllowAuthorizeAttribute"/> 特性标记跳过的授权验证服务基类。
        /// </summary>
        public static Type NDFAuthorizeAttribute
        {
            get
            {
                if (_authorizeAttributeType == null)
                {
                    _authorizeAttributeType = typeof(NDFAuthorizeAttribute);
                }
                return _authorizeAttributeType;
            }
        }
    }
}
